C.S.Burner 🪙 ━►🔥GIT Node
meshchatx/src/backend/page_node.py master (f0f6ed57) Text, 31.92 KB
T8b949e# SPDX-License-Identifier: 0BSD
T8b949e"""PageNode: Serves Micron pages and files over RNS.
Each PageNode owns an RNS Destination (SINGLE, IN) with the aspect
nomadnetwork.node and registers per-page request handlers at
paths like /page/index.mu. This makes page nodes compatible with
the standard NomadNet page browsing protocol (which is just RNS
request/response with specific path conventions).
Clients link to the destination and call link.request("/page/name.mu")
to fetch a page, or /file/name for files.
Supported page filename extensions are .mu, .md, .txt, and .html.
"""
Tff7b72import T7ee787contextlib
Tff7b72import T7ee787json
Tff7b72import T7ee787os
Tff7b72import T7ee787shlex
Tff7b72import T7ee787shutil
Tff7b72import T7ee787stat
Tff7b72import T7ee787subprocess
Tff7b72import T7ee787sys
Tff7b72import T7ee787threading
Tff7b72import T7ee787time
Tff7b72import T7ee787RNS
Te6edf3APP_NAME Tff7b72= Ta5d6ff"Ta5d6ffnomadnetworkTa5d6ff"
Te6edf3ASPECT Tff7b72= Ta5d6ff"Ta5d6ffnodeTa5d6ff"
Te6edf3DEFAULT_INDEX Tff7b72= Ta5d6ff"Ta5d6ffindex.muTa5d6ff"
Te6edf3ALLOWED_PAGE_EXTENSIONS Tff7b72= Tffa657frozensetTb4b4b4(Tb4b4b4{Ta5d6ff"Ta5d6ff.muTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff.mdTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff.txtTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff.htmlTa5d6ff"Tb4b4b4}Tb4b4b4)
Te6edf3DEFAULT_ANNOUNCE_INTERVAL_SECONDS Tff7b72= T79c0ff900
Te6edf3MIN_ANNOUNCE_INTERVAL_SECONDS Tff7b72= T79c0ff60
Te6edf3MAX_ANNOUNCE_INTERVAL_SECONDS Tff7b72= T79c0ff86400
Te6edf3EXECUTABLE_PAGE_TIMEOUT_SECONDS Tff7b72= T79c0ff15
Te6edf3MAX_UNIQUE_REMOTE_HASHES Tff7b72= T79c0ff4096
Te6edf3PAGE_GENERATION_FAILED_MICRON Tff7b72= Tb4b4b4(
Ta5d6ff"Ta5d6ff>Page Generation FailedTffea00\nTffea00\nTa5d6ffThe page could not be generated.Tffea00\nTa5d6ff"
Tb4b4b4)
T8b949e# Host env copied into executable page scripts. Request field_* / var_* cannot
T8b949e# overwrite these names. Windows Python needs SYSTEMROOT to start.
Te6edf3_EXECUTABLE_PAGE_HOST_ENV_KEYS Tff7b72= Tb4b4b4(
Ta5d6ff"Ta5d6ffPATHTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffSYSTEMROOTTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffWINDIRTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffSYSTEMDRIVETa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffPATHEXTTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffCOMSPECTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffTEMPTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffTMPTa5d6ff"Tb4b4b4,
Tb4b4b4)
Te6edf3_SHEBANG_INTERPRETER_ALIASES Tff7b72= Tb4b4b4{
Ta5d6ff"Ta5d6ffpythonTa5d6ff"Tb4b4b4: Tb4b4b4(Ta5d6ff"Ta5d6ffpythonTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffpython3Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffpyTa5d6ff"Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffpython3Ta5d6ff"Tb4b4b4: Tb4b4b4(Ta5d6ff"Ta5d6ffpython3Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffpythonTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffpyTa5d6ff"Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffpyTa5d6ff"Tb4b4b4: Tb4b4b4(Ta5d6ff"Ta5d6ffpyTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffpythonTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffpython3Ta5d6ff"Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffnodeTa5d6ff"Tb4b4b4: Tb4b4b4(Ta5d6ff"Ta5d6ffnodeTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffnodejsTa5d6ff"Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffnodejsTa5d6ff"Tb4b4b4: Tb4b4b4(Ta5d6ff"Ta5d6ffnodeTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffnodejsTa5d6ff"Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffshTa5d6ff"Tb4b4b4: Tb4b4b4(Ta5d6ff"Ta5d6ffbashTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffshTa5d6ff"Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffbashTa5d6ff"Tb4b4b4: Tb4b4b4(Ta5d6ff"Ta5d6ffbashTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffshTa5d6ff"Tb4b4b4)Tb4b4b4,
Tb4b4b4}
Tff7b72def Td2a8ffnormalize_announce_interval_secondsTb4b4b4(
Te6edf3valueTb4b4b4,
Te6edf3defaultTff7b72=Te6edf3DEFAULT_ANNOUNCE_INTERVAL_SECONDSTb4b4b4,
Tb4b4b4)Tb4b4b4:
T8b949e"""Clamp an announce interval to the supported range, or 0 to disable periodic announces."""
Tff7b72if Te6edf3value Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Tffa657intTb4b4b4(Te6edf3defaultTb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3seconds Tff7b72= Tffa657intTb4b4b4(Te6edf3valueTb4b4b4)
Tff7b72except Tb4b4b4(Tf85149TypeErrorTb4b4b4, Tf85149ValueErrorTb4b4b4)Tb4b4b4:
Tff7b72return Tffa657intTb4b4b4(Te6edf3defaultTb4b4b4)
Tff7b72if Te6edf3seconds Tff7b72<Tff7b72= T79c0ff0Tb4b4b4:
Tff7b72return T79c0ff0
Tff7b72return Tffa657maxTb4b4b4(
Te6edf3MIN_ANNOUNCE_INTERVAL_SECONDSTb4b4b4,
Tffa657minTb4b4b4(Te6edf3MAX_ANNOUNCE_INTERVAL_SECONDSTb4b4b4, Te6edf3secondsTb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72def Td2a8ffnormalize_page_filenameTb4b4b4(Te6edf3nameTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tffa657strTb4b4b4:
T8b949e"""Return a safe basename with an allowed extension. Unknown extensions raise ValueError."""
Te6edf3name Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffbasenameTb4b4b4(Tb4b4b4(Te6edf3name Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3name Tff7b72or Te6edf3name Tff7b72in Tb4b4b4(Ta5d6ff"Ta5d6ff.Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff..Ta5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6ff"Ta5d6ffpage name is requiredTa5d6ff"Tb4b4b4)
Tff7b72if Ta5d6ff"Ta5d6ff/Ta5d6ff" Tff7b72in Te6edf3name Tff7b72or Ta5d6ff"Tffea00\\Ta5d6ff" Tff7b72in Te6edf3nameTb4b4b4:
Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6ff"Ta5d6ffinvalid page nameTa5d6ff"Tb4b4b4)
Te6edf3lower Tff7b72= Te6edf3nameTff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)
Tff7b72for Te6edf3ext Tff7b72in Te6edf3ALLOWED_PAGE_EXTENSIONSTb4b4b4:
Tff7b72if Te6edf3lowerTff7b72.Td2a8ffendswithTb4b4b4(Te6edf3extTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3name
Tff7b72if Ta5d6ff"Ta5d6ff.Ta5d6ff" Tff7b72in Te6edf3nameTb4b4b4:
Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6ff"Ta5d6ffunsupported page extensionTa5d6ff"Tb4b4b4)
Tff7b72return Ta5d6fffTa5d6ff"Tffd700{Te6edf3nameTffd700}Ta5d6ff.muTa5d6ff"
Tff7b72def Td2a8ffis_allowed_page_filenameTb4b4b4(Te6edf3nameTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tffa657boolTb4b4b4:
Te6edf3lower Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffbasenameTb4b4b4(Te6edf3name Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4)Tff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)
Tff7b72return Tffa657anyTb4b4b4(Te6edf3lowerTff7b72.Td2a8ffendswithTb4b4b4(Te6edf3extTb4b4b4) Tff7b72for Te6edf3ext Tff7b72in Te6edf3ALLOWED_PAGE_EXTENSIONSTb4b4b4)
Tff7b72def Td2a8ff_safe_mesh_file_basenameTb4b4b4(Te6edf3nameTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tffa657strTb4b4b4:
T8b949e"""Reject empty, dot, or parent-segment names after basename (path traversal)."""
Te6edf3base Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffbasenameTb4b4b4(Tb4b4b4(Te6edf3name Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3base Tff7b72or Te6edf3base Tff7b72in Tb4b4b4(Ta5d6ff"Ta5d6ff.Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff..Ta5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6ff"Ta5d6ffinvalid file nameTa5d6ff"Tb4b4b4)
Tff7b72if Ta5d6ff"Ta5d6ff/Ta5d6ff" Tff7b72in Te6edf3base Tff7b72or Ta5d6ff"Tffea00\\Ta5d6ff" Tff7b72in Te6edf3baseTb4b4b4:
Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6ff"Ta5d6ffinvalid file nameTa5d6ff"Tb4b4b4)
Tff7b72return Te6edf3base
Tff7b72def Td2a8ff_path_is_under_rootTb4b4b4(Te6edf3resolvedTb4b4b4: Tffa657strTb4b4b4, Te6edf3rootTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tffa657boolTb4b4b4:
Tff7b72return Te6edf3resolved Tff7b72== Te6edf3root Tff7b72or Te6edf3resolvedTff7b72.Td2a8ffstartswithTb4b4b4(Te6edf3root Tff7b72+ Te6edf3osTff7b72.Td2a8ffsepTb4b4b4)
Tff7b72def Td2a8ff_is_windows_platformTb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657boolTb4b4b4:
Tff7b72if Te6edf3osTff7b72.Td2a8ffname Tff7b72== Ta5d6ff"Ta5d6ffntTa5d6ff"Tb4b4b4:
Tff7b72return Tff7b72True
Tff7b72tryTb4b4b4:
Tff7b72return Tffa657boolTb4b4b4(Te6edf3RNSTff7b72.Td2a8ffvendorTff7b72.Td2a8ffplatformutilsTff7b72.Td2a8ffis_windowsTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72return Tff7b72False
Tff7b72def Td2a8ff_page_generation_error_bytesTb4b4b4(Te6edf3reasonTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tffa657bytesTb4b4b4:
Te6edf3text Tff7b72= Te6edf3PAGE_GENERATION_FAILED_MICRON
Tff7b72if Te6edf3reasonTb4b4b4:
Te6edf3text Tff7b72+Tff7b72= Ta5d6fffTa5d6ff"Tffea00\nTffd700{Te6edf3reasonTffd700}Tffea00\nTa5d6ff"
Tff7b72return Te6edf3textTff7b72.Td2a8ffencodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4)
Tff7b72def Td2a8ff_normalize_executable_page_namesTb4b4b4(Te6edf3namesTb4b4b4) Tff7b72-Tff7b72> Tffa657listTb4b4b4[Tffa657strTb4b4b4]Tb4b4b4:
T8b949e"""Return unique allowed page filenames from a config list."""
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3namesTb4b4b4, Tffa657listTb4b4b4)Tb4b4b4:
Tff7b72return Tb4b4b4[Tb4b4b4]
Te6edf3outTb4b4b4: Tffa657listTb4b4b4[Tffa657strTb4b4b4] Tff7b72= Tb4b4b4[Tb4b4b4]
Te6edf3seenTb4b4b4: Tffa657setTb4b4b4[Tffa657strTb4b4b4] Tff7b72= Tffa657setTb4b4b4(Tb4b4b4)
Tff7b72for Te6edf3item Tff7b72in Te6edf3namesTb4b4b4:
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3itemTb4b4b4, Tffa657strTb4b4b4)Tb4b4b4:
Tff7b72continue
Tff7b72tryTb4b4b4:
Te6edf3safe Tff7b72= Te6edf3normalize_page_filenameTb4b4b4(Te6edf3itemTb4b4b4)
Tff7b72except Tf85149ValueErrorTb4b4b4:
Tff7b72continue
Tff7b72if Te6edf3safe Tff7b72in Te6edf3seenTb4b4b4:
Tff7b72continue
Te6edf3seenTff7b72.Td2a8ffaddTb4b4b4(Te6edf3safeTb4b4b4)
Te6edf3outTff7b72.Td2a8ffappendTb4b4b4(Te6edf3safeTb4b4b4)
Tff7b72return Te6edf3out
Tff7b72def Td2a8ff_parse_page_shebangTb4b4b4(Te6edf3page_pathTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tffa657tupleTb4b4b4[Tffa657strTb4b4b4, Tffa657listTb4b4b4[Tffa657strTb4b4b4]Tb4b4b4] Tff7b72| Tff7b72NoneTb4b4b4:
T8b949e"""Return (program, extra_args) from a page shebang, or None."""
Tff7b72tryTb4b4b4:
Tff7b72with Tffa657openTb4b4b4(Te6edf3page_pathTb4b4b4, Ta5d6ff"Ta5d6ffrbTa5d6ff"Tb4b4b4) Tff7b72as Te6edf3handleTb4b4b4:
Te6edf3first Tff7b72= Te6edf3handleTff7b72.Td2a8ffreadlineTb4b4b4(Tb4b4b4)
Tff7b72except Tf85149OSErrorTb4b4b4:
Tff7b72return Tff7b72None
Tff7b72if Tff7b72not Te6edf3firstTff7b72.Td2a8ffstartswithTb4b4b4(Ta5d6ffbTa5d6ff"Ta5d6ff#!Ta5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72None
Te6edf3line Tff7b72= Te6edf3firstTb4b4b4[T79c0ff2Tb4b4b4:Tb4b4b4]Tff7b72.Td2a8ffdecodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4, Te6edf3errorsTff7b72=Ta5d6ff"Ta5d6ffreplaceTa5d6ff"Tb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3lineTb4b4b4:
Tff7b72return Tff7b72None
Te6edf3windows_path Tff7b72= Tffa657lenTb4b4b4(Te6edf3lineTb4b4b4) Tff7b72>Tff7b72= T79c0ff3 Tff7b72and Te6edf3lineTb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8ffisalphaTb4b4b4(Tb4b4b4) Tff7b72and Te6edf3lineTb4b4b4[T79c0ff1Tb4b4b4] Tff7b72== Ta5d6ff"Ta5d6ff:Ta5d6ff"
Tff7b72tryTb4b4b4:
Te6edf3tokens Tff7b72= Te6edf3shlexTff7b72.Td2a8ffsplitTb4b4b4(Te6edf3lineTb4b4b4, Te6edf3posixTff7b72=Tff7b72not Te6edf3windows_pathTb4b4b4)
Tff7b72except Tf85149ValueErrorTb4b4b4:
Tff7b72return Tff7b72None
Tff7b72if Tff7b72not Te6edf3tokensTb4b4b4:
Tff7b72return Tff7b72None
Te6edf3program Tff7b72= Te6edf3tokensTb4b4b4[T79c0ff0Tb4b4b4]
Te6edf3rest Tff7b72= Te6edf3tokensTb4b4b4[T79c0ff1Tb4b4b4:Tb4b4b4]
Te6edf3base Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffbasenameTb4b4b4(Te6edf3programTff7b72.Td2a8ffreplaceTb4b4b4(Ta5d6ff"Tffea00\\Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff/Ta5d6ff"Tb4b4b4)Tb4b4b4)
Tff7b72if Te6edf3baseTff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4) Tff7b72in Tb4b4b4(Ta5d6ff"Ta5d6ffenvTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffenv.exeTa5d6ff"Tb4b4b4) Tff7b72and Te6edf3restTb4b4b4:
Tff7b72if Te6edf3restTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72== Ta5d6ff"Ta5d6ff-STa5d6ff"Tb4b4b4:
Te6edf3rest Tff7b72= Te6edf3restTb4b4b4[T79c0ff1Tb4b4b4:Tb4b4b4]
Tff7b72if Tff7b72not Te6edf3restTb4b4b4:
Tff7b72return Tff7b72None
Tff7b72return Te6edf3restTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, Te6edf3restTb4b4b4[T79c0ff1Tb4b4b4:Tb4b4b4]
Tff7b72return Te6edf3programTb4b4b4, Te6edf3rest
Tff7b72def Td2a8ff_shebang_lookup_namesTb4b4b4(Te6edf3nameTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tffa657tupleTb4b4b4[Tffa657strTb4b4b4, Tff7b72.Tff7b72.Tff7b72.Tb4b4b4]Tb4b4b4:
Te6edf3stem Tff7b72= Te6edf3name
Tff7b72if Te6edf3stemTff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)Tff7b72.Td2a8ffendswithTb4b4b4(Ta5d6ff"Ta5d6ff.exeTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3stem Tff7b72= Te6edf3stemTb4b4b4[Tb4b4b4:Tff7b72-T79c0ff4Tb4b4b4]
Te6edf3aliases Tff7b72= Te6edf3_SHEBANG_INTERPRETER_ALIASESTff7b72.Td2a8ffgetTb4b4b4(Te6edf3stemTff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72if Te6edf3aliasesTb4b4b4:
Tff7b72return Te6edf3aliases
Tff7b72if Te6edf3stem Tff7b72!= Te6edf3nameTb4b4b4:
Tff7b72return Tb4b4b4(Te6edf3nameTb4b4b4, Te6edf3stemTb4b4b4)
Tff7b72return Tb4b4b4(Te6edf3nameTb4b4b4,Tb4b4b4)
Tff7b72def Td2a8ff_resolve_shebang_interpreterTb4b4b4(Te6edf3programTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tffa657str Tff7b72| Tff7b72NoneTb4b4b4:
T8b949e"""Resolve a shebang program to an executable path on this host."""
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisabsTb4b4b4(Te6edf3programTb4b4b4) Tff7b72and Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisfileTb4b4b4(Te6edf3programTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3program
Te6edf3name Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffbasenameTb4b4b4(Te6edf3programTff7b72.Td2a8ffreplaceTb4b4b4(Ta5d6ff"Tffea00\\Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff/Ta5d6ff"Tb4b4b4)Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3name Tff7b72or Te6edf3name Tff7b72in Tb4b4b4(Ta5d6ff"Ta5d6ff.Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff..Ta5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72None
Te6edf3frozen Tff7b72= Tffa657boolTb4b4b4(Tffa657getattrTb4b4b4(Te6edf3sysTb4b4b4, Ta5d6ff"Ta5d6fffrozenTa5d6ff"Tb4b4b4, Tff7b72FalseTb4b4b4)Tb4b4b4)
Tff7b72for Te6edf3candidate Tff7b72in Te6edf3_shebang_lookup_namesTb4b4b4(Te6edf3nameTb4b4b4)Tb4b4b4:
Te6edf3found Tff7b72= Te6edf3shutilTff7b72.Td2a8ffwhichTb4b4b4(Te6edf3candidateTb4b4b4)
Tff7b72if Te6edf3foundTb4b4b4:
Tff7b72return Te6edf3found
Te6edf3stem Tff7b72= Te6edf3nameTff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3stemTff7b72.Td2a8ffendswithTb4b4b4(Ta5d6ff"Ta5d6ff.exeTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3stem Tff7b72= Te6edf3stemTb4b4b4[Tb4b4b4:Tff7b72-T79c0ff4Tb4b4b4]
Tff7b72if Tff7b72not Te6edf3frozen Tff7b72and Te6edf3stem Tff7b72in Tb4b4b4(Ta5d6ff"Ta5d6ffpythonTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffpython3Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffpyTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3executable Tff7b72= Te6edf3sysTff7b72.Td2a8ffexecutable
Tff7b72if Te6edf3executable Tff7b72and Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisfileTb4b4b4(Te6edf3executableTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3executable
Tff7b72return Tff7b72None
Tff7b72def Td2a8ff_windows_page_commandTb4b4b4(Te6edf3page_pathTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tffa657listTb4b4b4[Tffa657strTb4b4b4] Tff7b72| Tff7b72NoneTb4b4b4:
T8b949e"""Build argv to run a page script on Windows via its shebang."""
Te6edf3parsed Tff7b72= Te6edf3_parse_page_shebangTb4b4b4(Te6edf3page_pathTb4b4b4)
Tff7b72if Te6edf3parsed Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Tff7b72None
Te6edf3programTb4b4b4, Te6edf3extra Tff7b72= Te6edf3parsed
Te6edf3interpreter Tff7b72= Te6edf3_resolve_shebang_interpreterTb4b4b4(Te6edf3programTb4b4b4)
Tff7b72if Te6edf3interpreter Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Tff7b72None
Tff7b72return Tb4b4b4[Te6edf3interpreterTb4b4b4, Tff7b72*Te6edf3extraTb4b4b4, Te6edf3page_pathTb4b4b4]
Tff7b72def Td2a8ff_build_executable_page_envTb4b4b4(
Te6edf3dataTb4b4b4,
Te6edf3link_idTff7b72=Tff7b72NoneTb4b4b4,
Te6edf3remote_identityTff7b72=Tff7b72NoneTb4b4b4,
Tb4b4b4) Tff7b72-Tff7b72> Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Tffa657strTb4b4b4]Tb4b4b4:
Te6edf3env_mapTb4b4b4: Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Tffa657strTb4b4b4] Tff7b72= Tb4b4b4{Tb4b4b4}
Tff7b72for Te6edf3key Tff7b72in Te6edf3_EXECUTABLE_PAGE_HOST_ENV_KEYSTb4b4b4:
Tff7b72if Te6edf3key Tff7b72in Te6edf3osTff7b72.Td2a8ffenvironTb4b4b4:
Te6edf3env_mapTb4b4b4[Te6edf3keyTb4b4b4] Tff7b72= Te6edf3osTff7b72.Td2a8ffenvironTb4b4b4[Te6edf3keyTb4b4b4]
Tff7b72if Te6edf3link_id Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3env_mapTb4b4b4[Ta5d6ff"Ta5d6fflink_idTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3RNSTff7b72.Td2a8ffhexrepTb4b4b4(Te6edf3link_idTb4b4b4, Te6edf3delimitTff7b72=Tff7b72FalseTb4b4b4)
Tff7b72if Te6edf3remote_identity Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3remote_hash Tff7b72= Tffa657getattrTb4b4b4(Te6edf3remote_identityTb4b4b4, Ta5d6ff"Ta5d6ffhashTa5d6ff"Tb4b4b4, Tff7b72NoneTb4b4b4)
Tff7b72if Te6edf3remote_hash Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Te6edf3env_mapTb4b4b4[Ta5d6ff"Ta5d6ffremote_identityTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3RNSTff7b72.Td2a8ffhexrepTb4b4b4(Te6edf3remote_hashTb4b4b4, Te6edf3delimitTff7b72=Tff7b72FalseTb4b4b4)
Tff7b72if Te6edf3data Tff7b72is Tff7b72not Tff7b72None Tff7b72and Tffa657isinstanceTb4b4b4(Te6edf3dataTb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4:
Tff7b72for Te6edf3keyTb4b4b4, Te6edf3value Tff7b72in Te6edf3dataTff7b72.Td2a8ffitemsTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3keyTb4b4b4, Tffa657strTb4b4b4) Tff7b72and Tb4b4b4(
Te6edf3keyTff7b72.Td2a8ffstartswithTb4b4b4(Ta5d6ff"Ta5d6fffield_Ta5d6ff"Tb4b4b4) Tff7b72or Te6edf3keyTff7b72.Td2a8ffstartswithTb4b4b4(Ta5d6ff"Ta5d6ffvar_Ta5d6ff"Tb4b4b4)
Tb4b4b4)Tb4b4b4:
Te6edf3env_mapTb4b4b4[Te6edf3keyTb4b4b4] Tff7b72= Tffa657strTb4b4b4(Te6edf3valueTb4b4b4)
Tff7b72return Te6edf3env_map
Tff7b72def Td2a8ff_reject_name_component_too_longTb4b4b4(Te6edf3parent_dirTb4b4b4: Tffa657strTb4b4b4, Te6edf3componentTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
T8b949e"""Raise ValueError if basename exceeds this directory's filename length limit."""
Tff7b72tryTb4b4b4:
Tff7b72if Te6edf3parent_dir Tff7b72and Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Te6edf3parent_dirTb4b4b4)Tb4b4b4:
Te6edf3max_bytes Tff7b72= Tffa657intTb4b4b4(Te6edf3osTff7b72.Td2a8ffpathconfTb4b4b4(Te6edf3parent_dirTb4b4b4, Ta5d6ff"Ta5d6ffPC_NAME_MAXTa5d6ff"Tb4b4b4)Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3max_bytes Tff7b72= T79c0ff255
Tff7b72except Tb4b4b4(Tf85149OSErrorTb4b4b4, Tf85149ValueErrorTb4b4b4, Tf85149TypeErrorTb4b4b4, Tf85149OverflowErrorTb4b4b4)Tb4b4b4:
Te6edf3max_bytes Tff7b72= T79c0ff255
Tff7b72if Tffa657lenTb4b4b4(Te6edf3osTff7b72.Td2a8fffsencodeTb4b4b4(Te6edf3componentTb4b4b4)Tb4b4b4) Tff7b72> Te6edf3max_bytesTb4b4b4:
Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6ff"Ta5d6ffname too longTa5d6ff"Tb4b4b4)
Tff7b72class T56d364PageNodeTb4b4b4:
T8b949e"""A single page-serving node on the Reticulum mesh."""
Tff7b72def Tff7b72__init__Tb4b4b4(
Tff7b72selfTb4b4b4,
Te6edf3node_idTb4b4b4,
Te6edf3nameTb4b4b4,
Te6edf3base_dirTb4b4b4,
Te6edf3identityTff7b72=Tff7b72NoneTb4b4b4,
Te6edf3identity_pathTff7b72=Tff7b72NoneTb4b4b4,
Te6edf3announce_enabledTff7b72=Tff7b72TrueTb4b4b4,
Te6edf3announce_interval_secondsTff7b72=Te6edf3DEFAULT_ANNOUNCE_INTERVAL_SECONDSTb4b4b4,
Te6edf3executable_pages_enabledTff7b72=Tff7b72FalseTb4b4b4,
Te6edf3executable_page_namesTff7b72=Tff7b72NoneTb4b4b4,
Te6edf3on_announceTff7b72=Tff7b72NoneTb4b4b4,
Tb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffnode_id Tff7b72= Te6edf3node_id
Tff7b72selfTff7b72.Td2a8ffname Tff7b72= Te6edf3name
Tff7b72selfTff7b72.Td2a8ffbase_dir Tff7b72= Te6edf3base_dir
Tff7b72selfTff7b72.Td2a8ffpages_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3base_dirTb4b4b4, Ta5d6ff"Ta5d6ffpagesTa5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8fffiles_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3base_dirTb4b4b4, Ta5d6ff"Ta5d6fffilesTa5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffidentity Tff7b72= Te6edf3identity
Tff7b72selfTff7b72.Td2a8ffidentity_path Tff7b72= Te6edf3identity_path Tff7b72or Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3base_dirTb4b4b4, Ta5d6ff"Ta5d6ffidentityTa5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffdestination Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ffactive_links Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72selfTff7b72.Td2a8ffrunning Tff7b72= Tff7b72False
Tff7b72selfTff7b72.Td2a8ff_registered_page_paths Tff7b72= Tffa657setTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_registered_file_paths Tff7b72= Tffa657setTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_stats Tff7b72= Tb4b4b4{Ta5d6ff"Ta5d6ffpages_servedTa5d6ff"Tb4b4b4: T79c0ff0Tb4b4b4, Ta5d6ff"Ta5d6fffiles_servedTa5d6ff"Tb4b4b4: T79c0ff0Tb4b4b4, Ta5d6ff"Ta5d6fflinks_establishedTa5d6ff"Tb4b4b4: T79c0ff0Tb4b4b4}
Tff7b72selfTff7b72.Td2a8ff_serve_started_at Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ff_unique_remote_hashes Tff7b72= Tffa657setTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffannounce_enabled Tff7b72= Tffa657boolTb4b4b4(Te6edf3announce_enabledTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffannounce_interval_seconds Tff7b72= Te6edf3normalize_announce_interval_secondsTb4b4b4(
Te6edf3announce_interval_secondsTb4b4b4,
Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffexecutable_pages_enabled Tff7b72= Tffa657boolTb4b4b4(Te6edf3executable_pages_enabledTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_executable_page_names Tff7b72= Tffa657setTb4b4b4(
Te6edf3_normalize_executable_page_namesTb4b4b4(Te6edf3executable_page_namesTb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72selfTff7b72.Td2a8fflast_announced_at Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ffon_announce Tff7b72= Te6edf3on_announce
Tff7b72selfTff7b72.Td2a8ff_announce_timer Tff7b72= Tff7b72None
Tff7b72def Td2a8ffsetupTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Create directories, load or create identity, set up RNS destination."""
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Tff7b72selfTff7b72.Td2a8ffpages_dirTb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Tff7b72selfTff7b72.Td2a8fffiles_dirTb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72if Tff7b72selfTff7b72.Td2a8ffidentity Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisfileTb4b4b4(Tff7b72selfTff7b72.Td2a8ffidentity_pathTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffidentity Tff7b72= Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8fffrom_fileTb4b4b4(Tff7b72selfTff7b72.Td2a8ffidentity_pathTb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffidentity Tff7b72= Te6edf3RNSTff7b72.Td2a8ffIdentityTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffidentityTff7b72.Td2a8ffto_fileTb4b4b4(Tff7b72selfTff7b72.Td2a8ffidentity_pathTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffdestination Tff7b72= Te6edf3RNSTff7b72.Td2a8ffDestinationTb4b4b4(
Tff7b72selfTff7b72.Td2a8ffidentityTb4b4b4,
Te6edf3RNSTff7b72.Td2a8ffDestinationTff7b72.Td2a8ffINTb4b4b4,
Te6edf3RNSTff7b72.Td2a8ffDestinationTff7b72.Td2a8ffSINGLETb4b4b4,
Te6edf3APP_NAMETb4b4b4,
Te6edf3ASPECTTb4b4b4,
Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8ffset_link_established_callbackTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_link_establishedTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_register_existing_pagesTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_register_existing_filesTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_ensure_local_pathTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffrunning Tff7b72= Tff7b72True
Tff7b72selfTff7b72.Td2a8ff_serve_started_at Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Tff7b72if Tff7b72selfTff7b72.Td2a8ffannounce_enabledTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffannounceTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_sync_announce_timerTb4b4b4(Tb4b4b4)
Tff7b72return Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8ffhashTff7b72.Td2a8ffhexTb4b4b4(Tb4b4b4)
Tff7b72def Td2a8ffannounceTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Broadcast this node's presence on the mesh."""
Tff7b72if Tff7b72selfTff7b72.Td2a8ffdestination Tff7b72and Tff7b72selfTff7b72.Td2a8ffrunningTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_register_existing_filesTb4b4b4(Tb4b4b4)
Te6edf3app_data Tff7b72= Tff7b72selfTff7b72.Td2a8ffnameTff7b72.Td2a8ffencodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8ffannounceTb4b4b4(Te6edf3app_dataTff7b72=Te6edf3app_dataTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_ensure_local_pathTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8fflast_announced_at Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Tff7b72if Tff7b72selfTff7b72.Td2a8ffon_announce Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffon_announceTb4b4b4(Tff7b72selfTb4b4b4)
Tff7b72def Td2a8ff_cancel_announce_timerTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Cancel the pending periodic announce timer, if any."""
Te6edf3timer Tff7b72= Tff7b72selfTff7b72.Td2a8ff_announce_timer
Tff7b72selfTff7b72.Td2a8ff_announce_timer Tff7b72= Tff7b72None
Tff7b72if Te6edf3timer Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3timerTff7b72.Td2a8ffcancelTb4b4b4(Tb4b4b4)
Tff7b72def Td2a8ff_sync_announce_timerTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Reschedule the periodic announce timer to match current settings."""
Tff7b72selfTff7b72.Td2a8ff_cancel_announce_timerTb4b4b4(Tb4b4b4)
Tff7b72if Tff7b72not Tff7b72selfTff7b72.Td2a8ffrunning Tff7b72or Tff7b72not Tff7b72selfTff7b72.Td2a8ffannounce_enabledTb4b4b4:
Tff7b72return
Te6edf3interval Tff7b72= Te6edf3normalize_announce_interval_secondsTb4b4b4(
Tff7b72selfTff7b72.Td2a8ffannounce_interval_secondsTb4b4b4,
Te6edf3defaultTff7b72=T79c0ff0Tb4b4b4,
Tb4b4b4)
Tff7b72if Te6edf3interval Tff7b72<Tff7b72= T79c0ff0Tb4b4b4:
Tff7b72return
Te6edf3timer Tff7b72= Te6edf3threadingTff7b72.Td2a8ffTimerTb4b4b4(Te6edf3intervalTb4b4b4, Tff7b72selfTff7b72.Td2a8ff_announce_timer_fireTb4b4b4)
Te6edf3timerTff7b72.Td2a8ffdaemon Tff7b72= Tff7b72True
Tff7b72selfTff7b72.Td2a8ff_announce_timer Tff7b72= Te6edf3timer
Te6edf3timerTff7b72.Td2a8ffstartTb4b4b4(Tb4b4b4)
Tff7b72def Td2a8ff_announce_timer_fireTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Timer callback: announce then reschedule for the next interval."""
Tff7b72selfTff7b72.Td2a8ff_announce_timer Tff7b72= Tff7b72None
Tff7b72if Tff7b72not Tff7b72selfTff7b72.Td2a8ffrunning Tff7b72or Tff7b72not Tff7b72selfTff7b72.Td2a8ffannounce_enabledTb4b4b4:
Tff7b72return
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffannounceTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_sync_announce_timerTb4b4b4(Tb4b4b4)
Tff7b72def Td2a8ffset_announce_settingsTb4b4b4(
Tff7b72selfTb4b4b4, Te6edf3announce_enabledTff7b72=Tff7b72NoneTb4b4b4, Te6edf3announce_interval_secondsTff7b72=Tff7b72None
Tb4b4b4)Tb4b4b4:
T8b949e"""Update announce enablement and/or interval, then resync the periodic timer."""
Tff7b72if Te6edf3announce_enabled Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffannounce_enabled Tff7b72= Tffa657boolTb4b4b4(Te6edf3announce_enabledTb4b4b4)
Tff7b72if Te6edf3announce_interval_seconds Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffannounce_interval_seconds Tff7b72= Te6edf3normalize_announce_interval_secondsTb4b4b4(
Te6edf3announce_interval_secondsTb4b4b4,
Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_sync_announce_timerTb4b4b4(Tb4b4b4)
Tff7b72def Td2a8ffset_executable_pages_enabledTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3enabledTb4b4b4)Tb4b4b4:
T8b949e"""Enable or disable dynamic executable page serving for this node."""
Tff7b72selfTff7b72.Td2a8ffexecutable_pages_enabled Tff7b72= Tffa657boolTb4b4b4(Te6edf3enabledTb4b4b4)
Tff7b72def Td2a8ffteardownTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Deregister handlers and clean up."""
Tff7b72selfTff7b72.Td2a8ffrunning Tff7b72= Tff7b72False
Tff7b72selfTff7b72.Td2a8ff_cancel_announce_timerTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_serve_started_at Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ff_unique_remote_hashesTff7b72.Td2a8ffclearTb4b4b4(Tb4b4b4)
Tff7b72if Tff7b72selfTff7b72.Td2a8ffdestinationTb4b4b4:
Tff7b72for Te6edf3rpath Tff7b72in Tffa657listTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_registered_page_pathsTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8ffderegister_request_handlerTb4b4b4(Te6edf3rpathTb4b4b4)
Tff7b72for Te6edf3rpath Tff7b72in Tffa657listTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_registered_file_pathsTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8ffderegister_request_handlerTb4b4b4(Te6edf3rpathTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_registered_page_pathsTff7b72.Td2a8ffclearTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_registered_file_pathsTff7b72.Td2a8ffclearTb4b4b4(Tb4b4b4)
Te6edf3RNSTff7b72.Td2a8ffTransportTff7b72.Td2a8ffderegister_destinationTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdestinationTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffdestination Tff7b72= Tff7b72None
Tff7b72for Te6edf3link Tff7b72in Tffa657listTb4b4b4(Tff7b72selfTff7b72.Td2a8ffactive_linksTb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3linkTff7b72.Td2a8ffteardownTb4b4b4(Tb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72pass
Tff7b72selfTff7b72.Td2a8ffactive_linksTff7b72.Td2a8ffclearTb4b4b4(Tb4b4b4)
Tff7b72def Td2a8ff_note_remote_identityTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3remote_identityTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3remote_identity Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return
Tff7b72tryTb4b4b4:
Te6edf3h Tff7b72= Tffa657getattrTb4b4b4(Te6edf3remote_identityTb4b4b4, Ta5d6ff"Ta5d6ffhashTa5d6ff"Tb4b4b4, Tff7b72NoneTb4b4b4)
Tff7b72if Te6edf3h Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72if Tffa657lenTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_unique_remote_hashesTb4b4b4) Tff7b72>Tff7b72= Te6edf3MAX_UNIQUE_REMOTE_HASHESTb4b4b4:
Tff7b72return
Tff7b72selfTff7b72.Td2a8ff_unique_remote_hashesTff7b72.Td2a8ffaddTb4b4b4(Te6edf3hTff7b72.Td2a8ffhexTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72pass
Tff7b72def Td2a8ff_link_establishedTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3linkTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffactive_linksTff7b72.Td2a8ffappendTb4b4b4(Te6edf3linkTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_statsTb4b4b4[Ta5d6ff"Ta5d6fflinks_establishedTa5d6ff"Tb4b4b4] Tff7b72+Tff7b72= T79c0ff1
Tff7b72tryTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_note_remote_identityTb4b4b4(Te6edf3linkTff7b72.Td2a8ffget_remote_identityTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72pass
Te6edf3linkTff7b72.Td2a8ffset_link_closed_callbackTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_link_closedTb4b4b4)
Tff7b72def Td2a8ff_link_closedTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3linkTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3link Tff7b72in Tff7b72selfTff7b72.Td2a8ffactive_linksTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffactive_linksTff7b72.Td2a8ffremoveTb4b4b4(Te6edf3linkTb4b4b4)
Tff7b72def Td2a8ff_ensure_local_pathTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Register this identity in RNS.Identity.known_destinations.
Lets Identity.recall() resolve the destination for local link setup.
"""
Tff7b72if Tff7b72not Tff7b72selfTff7b72.Td2a8ffdestinationTb4b4b4:
Tff7b72return
Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8ffrememberTb4b4b4(
Te6edf3packet_hashTff7b72=Tff7b72NoneTb4b4b4,
Te6edf3destination_hashTff7b72=Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8ffhashTb4b4b4,
Te6edf3public_keyTff7b72=Tff7b72selfTff7b72.Td2a8ffidentityTff7b72.Td2a8ffget_public_keyTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3app_dataTff7b72=Tff7b72selfTff7b72.Td2a8ffnameTff7b72.Td2a8ffencodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72def Td2a8ff_page_request_pathTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3page_nameTb4b4b4)Tb4b4b4:
T8b949e"""Build the NomadNet-style request path for a page."""
Tff7b72return Ta5d6fffTa5d6ff"Ta5d6ff/page/Tffd700{Te6edf3page_nameTffd700}Ta5d6ff"
Tff7b72def Td2a8ff_file_request_pathTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3file_nameTb4b4b4)Tb4b4b4:
T8b949e"""Build the NomadNet-style request path for a file."""
Tff7b72return Ta5d6fffTa5d6ff"Ta5d6ff/file/Tffd700{Te6edf3file_nameTffd700}Ta5d6ff"
Tff7b72def Td2a8ff_register_existing_pagesTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Scan pages directory and register a handler for each page."""
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Tff7b72selfTff7b72.Td2a8ffpages_dirTb4b4b4)Tb4b4b4:
Tff7b72return
Tff7b72for Te6edf3fname Tff7b72in Te6edf3osTff7b72.Td2a8fflistdirTb4b4b4(Tff7b72selfTff7b72.Td2a8ffpages_dirTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ff_jail_page_pathTb4b4b4(Te6edf3fnameTb4b4b4, Te6edf3must_existTff7b72=Tff7b72TrueTb4b4b4) Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72continue
Tff7b72selfTff7b72.Td2a8ff_register_page_handlerTb4b4b4(Te6edf3fnameTb4b4b4)
Tff7b72def Td2a8ff_register_existing_filesTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Scan files directory and register a handler for each file."""
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Tff7b72selfTff7b72.Td2a8fffiles_dirTb4b4b4)Tb4b4b4:
Tff7b72return
Tff7b72for Te6edf3fname Tff7b72in Te6edf3osTff7b72.Td2a8fflistdirTb4b4b4(Tff7b72selfTff7b72.Td2a8fffiles_dirTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ff_jail_file_pathTb4b4b4(Te6edf3fnameTb4b4b4, Te6edf3must_existTff7b72=Tff7b72TrueTb4b4b4) Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72continue
Tff7b72selfTff7b72.Td2a8ff_register_file_handlerTb4b4b4(Te6edf3fnameTb4b4b4)
Tff7b72def Td2a8ff_register_page_handlerTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3page_nameTb4b4b4)Tb4b4b4:
T8b949e"""Register a request handler for a specific page."""
Tff7b72if Tff7b72not Tff7b72selfTff7b72.Td2a8ffdestinationTb4b4b4:
Tff7b72return
Te6edf3rpath Tff7b72= Tff7b72selfTff7b72.Td2a8ff_page_request_pathTb4b4b4(Te6edf3page_nameTb4b4b4)
Tff7b72if Te6edf3rpath Tff7b72in Tff7b72selfTff7b72.Td2a8ff_registered_page_pathsTb4b4b4:
Tff7b72return
Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8ffregister_request_handlerTb4b4b4(
Te6edf3rpathTb4b4b4,
Te6edf3response_generatorTff7b72=Tff7b72selfTff7b72.Td2a8ff_make_page_responderTb4b4b4(Te6edf3page_nameTb4b4b4)Tb4b4b4,
Te6edf3allowTff7b72=Te6edf3RNSTff7b72.Td2a8ffDestinationTff7b72.Td2a8ffALLOW_ALLTb4b4b4,
Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_registered_page_pathsTff7b72.Td2a8ffaddTb4b4b4(Te6edf3rpathTb4b4b4)
Tff7b72def Td2a8ff_deregister_page_handlerTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3page_nameTb4b4b4)Tb4b4b4:
T8b949e"""Deregister the request handler for a specific page."""
Tff7b72if Tff7b72not Tff7b72selfTff7b72.Td2a8ffdestinationTb4b4b4:
Tff7b72return
Te6edf3rpath Tff7b72= Tff7b72selfTff7b72.Td2a8ff_page_request_pathTb4b4b4(Te6edf3page_nameTb4b4b4)
Tff7b72if Te6edf3rpath Tff7b72not Tff7b72in Tff7b72selfTff7b72.Td2a8ff_registered_page_pathsTb4b4b4:
Tff7b72return
Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8ffderegister_request_handlerTb4b4b4(Te6edf3rpathTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_registered_page_pathsTff7b72.Td2a8ffdiscardTb4b4b4(Te6edf3rpathTb4b4b4)
Tff7b72def Td2a8ff_register_file_handlerTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3file_nameTb4b4b4)Tb4b4b4:
T8b949e"""Register a request handler for a specific file."""
Tff7b72if Tff7b72not Tff7b72selfTff7b72.Td2a8ffdestinationTb4b4b4:
Tff7b72return
Te6edf3rpath Tff7b72= Tff7b72selfTff7b72.Td2a8ff_file_request_pathTb4b4b4(Te6edf3file_nameTb4b4b4)
Tff7b72if Te6edf3rpath Tff7b72in Tff7b72selfTff7b72.Td2a8ff_registered_file_pathsTb4b4b4:
Tff7b72return
Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8ffregister_request_handlerTb4b4b4(
Te6edf3rpathTb4b4b4,
Te6edf3response_generatorTff7b72=Tff7b72selfTff7b72.Td2a8ff_make_file_responderTb4b4b4(Te6edf3file_nameTb4b4b4)Tb4b4b4,
Te6edf3allowTff7b72=Te6edf3RNSTff7b72.Td2a8ffDestinationTff7b72.Td2a8ffALLOW_ALLTb4b4b4,
Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_registered_file_pathsTff7b72.Td2a8ffaddTb4b4b4(Te6edf3rpathTb4b4b4)
Tff7b72def Td2a8ff_deregister_file_handlerTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3file_nameTb4b4b4)Tb4b4b4:
T8b949e"""Deregister the request handler for a specific file."""
Tff7b72if Tff7b72not Tff7b72selfTff7b72.Td2a8ffdestinationTb4b4b4:
Tff7b72return
Te6edf3rpath Tff7b72= Tff7b72selfTff7b72.Td2a8ff_file_request_pathTb4b4b4(Te6edf3file_nameTb4b4b4)
Tff7b72if Te6edf3rpath Tff7b72not Tff7b72in Tff7b72selfTff7b72.Td2a8ff_registered_file_pathsTb4b4b4:
Tff7b72return
Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8ffderegister_request_handlerTb4b4b4(Te6edf3rpathTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_registered_file_pathsTff7b72.Td2a8ffdiscardTb4b4b4(Te6edf3rpathTb4b4b4)
Tff7b72def Td2a8ff_jail_page_pathTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3nameTb4b4b4, Tff7b72*Tb4b4b4, Te6edf3must_existTff7b72=Tff7b72FalseTb4b4b4)Tb4b4b4:
T8b949e"""Resolve a page name under pages_dir after realpath.
Returns None when the name is invalid, the path escapes the jail
(including symlink-out), or must_exist is set and the file is missing.
"""
Tff7b72tryTb4b4b4:
Te6edf3safe_name Tff7b72= Te6edf3normalize_page_filenameTb4b4b4(Te6edf3nameTb4b4b4)
Te6edf3_reject_name_component_too_longTb4b4b4(Tff7b72selfTff7b72.Td2a8ffpages_dirTb4b4b4, Te6edf3safe_nameTb4b4b4)
Tff7b72except Tf85149ValueErrorTb4b4b4:
Tff7b72return Tff7b72None
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Tff7b72selfTff7b72.Td2a8ffpages_dirTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72None
Te6edf3root Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffrealpathTb4b4b4(Tff7b72selfTff7b72.Td2a8ffpages_dirTb4b4b4)
Te6edf3raw Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3rootTb4b4b4, Te6edf3safe_nameTb4b4b4)
Te6edf3resolved Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffrealpathTb4b4b4(Te6edf3rawTb4b4b4)
Tff7b72if Tff7b72not Te6edf3_path_is_under_rootTb4b4b4(Te6edf3resolvedTb4b4b4, Te6edf3rootTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72None
Tff7b72if Te6edf3must_exist Tff7b72and Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisfileTb4b4b4(Te6edf3resolvedTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72None
Tff7b72return Te6edf3resolved
Tff7b72def Td2a8ff_resolve_page_pathTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3nameTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ff_jail_page_pathTb4b4b4(Te6edf3nameTb4b4b4, Te6edf3must_existTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72def Td2a8ffis_page_executableTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3nameTb4b4b4)Tb4b4b4:
T8b949e"""Return whether this page is marked executable for dynamic serving."""
Te6edf3page_path Tff7b72= Tff7b72selfTff7b72.Td2a8ff_resolve_page_pathTb4b4b4(Te6edf3nameTb4b4b4)
Tff7b72if Te6edf3page_path Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Tff7b72False
Tff7b72return Tff7b72selfTff7b72.Td2a8ff_is_page_marked_executableTb4b4b4(Te6edf3page_pathTb4b4b4)
Tff7b72def Td2a8ff_is_page_marked_executableTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3page_pathTb4b4b4)Tb4b4b4:
Te6edf3name Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffbasenameTb4b4b4(Te6edf3page_pathTb4b4b4)
Tff7b72if Te6edf3name Tff7b72in Tff7b72selfTff7b72.Td2a8ff_executable_page_namesTb4b4b4:
Tff7b72return Tff7b72True
Tff7b72if Te6edf3_is_windows_platformTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72False
Tff7b72return Te6edf3osTff7b72.Td2a8ffaccessTb4b4b4(Te6edf3page_pathTb4b4b4, Te6edf3osTff7b72.Td2a8ffX_OKTb4b4b4)
Tff7b72def Td2a8ffset_page_executableTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3nameTb4b4b4, Te6edf3enabledTb4b4b4)Tb4b4b4:
T8b949e"""Mark or unmark a page as executable and persist the flag."""
Te6edf3page_path Tff7b72= Tff7b72selfTff7b72.Td2a8ff_resolve_page_pathTb4b4b4(Te6edf3nameTb4b4b4)
Tff7b72if Te6edf3page_path Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6ff"Ta5d6ffpage not foundTa5d6ff"Tb4b4b4)
Te6edf3name Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffbasenameTb4b4b4(Te6edf3page_pathTb4b4b4)
Tff7b72if Te6edf3enabledTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_executable_page_namesTff7b72.Td2a8ffaddTb4b4b4(Te6edf3nameTb4b4b4)
Tff7b72if Tff7b72not Te6edf3_is_windows_platformTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3mode Tff7b72= Te6edf3osTff7b72.Td2a8ffstatTb4b4b4(Te6edf3page_pathTb4b4b4)Tff7b72.Td2a8ffst_mode
Te6edf3osTff7b72.Td2a8ffchmodTb4b4b4(Te6edf3page_pathTb4b4b4, Te6edf3mode Tff7b72| Te6edf3statTff7b72.Td2a8ffS_IXUSR Tff7b72| Te6edf3statTff7b72.Td2a8ffS_IXGRP Tff7b72| Te6edf3statTff7b72.Td2a8ffS_IXOTHTb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_executable_page_namesTff7b72.Td2a8ffdiscardTb4b4b4(Te6edf3nameTb4b4b4)
Tff7b72if Tff7b72not Te6edf3_is_windows_platformTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3mode Tff7b72= Te6edf3osTff7b72.Td2a8ffstatTb4b4b4(Te6edf3page_pathTb4b4b4)Tff7b72.Td2a8ffst_mode
Te6edf3osTff7b72.Td2a8ffchmodTb4b4b4(
Te6edf3page_pathTb4b4b4,
Te6edf3mode Tff7b72& Tff7b72~Tb4b4b4(Te6edf3statTff7b72.Td2a8ffS_IXUSR Tff7b72| Te6edf3statTff7b72.Td2a8ffS_IXGRP Tff7b72| Te6edf3statTff7b72.Td2a8ffS_IXOTHTb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffsave_configTb4b4b4(Tb4b4b4)
Tff7b72def Td2a8ff_should_execute_pageTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3page_pathTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72not Tff7b72selfTff7b72.Td2a8ffexecutable_pages_enabledTb4b4b4:
Tff7b72return Tff7b72False
Tff7b72return Tff7b72selfTff7b72.Td2a8ff_is_page_marked_executableTb4b4b4(Te6edf3page_pathTb4b4b4)
Tff7b72def Td2a8ff_read_static_page_bytesTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3page_pathTb4b4b4)Tb4b4b4:
Tff7b72with Tffa657openTb4b4b4(Te6edf3page_pathTb4b4b4, Ta5d6ff"Ta5d6ffrbTa5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Tff7b72return Te6edf3fTff7b72.Td2a8ffreadTb4b4b4(Tb4b4b4)
Tff7b72def Td2a8ff_execute_page_bytesTb4b4b4(
Tff7b72selfTb4b4b4, Te6edf3page_pathTb4b4b4, Te6edf3dataTff7b72=Tff7b72NoneTb4b4b4, Te6edf3link_idTff7b72=Tff7b72NoneTb4b4b4, Te6edf3remote_identityTff7b72=Tff7b72None
Tb4b4b4)Tb4b4b4:
Te6edf3env_map Tff7b72= Te6edf3_build_executable_page_envTb4b4b4(Te6edf3dataTb4b4b4, Te6edf3link_idTb4b4b4, Te6edf3remote_identityTb4b4b4)
Te6edf3run_kwargs Tff7b72= Tb4b4b4{
Ta5d6ff"Ta5d6ffstdoutTa5d6ff"Tb4b4b4: Te6edf3subprocessTff7b72.Td2a8ffPIPETb4b4b4,
Ta5d6ff"Ta5d6ffstderrTa5d6ff"Tb4b4b4: Te6edf3subprocessTff7b72.Td2a8ffDEVNULLTb4b4b4,
Ta5d6ff"Ta5d6ffenvTa5d6ff"Tb4b4b4: Te6edf3env_mapTb4b4b4,
Ta5d6ff"Ta5d6fftimeoutTa5d6ff"Tb4b4b4: Te6edf3EXECUTABLE_PAGE_TIMEOUT_SECONDSTb4b4b4,
Tb4b4b4}
Tff7b72if Te6edf3_is_windows_platformTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3command Tff7b72= Te6edf3_windows_page_commandTb4b4b4(Te6edf3page_pathTb4b4b4)
Tff7b72if Te6edf3command Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Te6edf3_page_generation_error_bytesTb4b4b4(
Ta5d6ff"Ta5d6ffCould not resolve a script interpreter from the page shebang.Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Te6edf3env_mapTff7b72.Td2a8ffsetdefaultTb4b4b4(Ta5d6ff"Ta5d6ffPYTHONIOENCODINGTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4)
Tff7b72if Te6edf3osTff7b72.Td2a8ffname Tff7b72== Ta5d6ff"Ta5d6ffntTa5d6ff"Tb4b4b4:
Te6edf3run_kwargsTb4b4b4[Ta5d6ff"Ta5d6ffcreationflagsTa5d6ff"Tb4b4b4] Tff7b72= Tffa657getattrTb4b4b4(
Te6edf3subprocessTb4b4b4,
Ta5d6ff"Ta5d6ffCREATE_NO_WINDOWTa5d6ff"Tb4b4b4,
T79c0ff0x08000000Tb4b4b4,
Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3command Tff7b72= Tb4b4b4[Te6edf3page_pathTb4b4b4]
Tff7b72tryTb4b4b4:
Te6edf3generated Tff7b72= Te6edf3subprocessTff7b72.Td2a8ffrunTb4b4b4(Te6edf3commandTb4b4b4, Tff7b72*Tff7b72*Te6edf3run_kwargsTb4b4b4)
Tff7b72return Te6edf3generatedTff7b72.Td2a8ffstdout
Tff7b72except Te6edf3subprocessTff7b72.Td2a8ffTimeoutExpiredTb4b4b4:
Tff7b72return Te6edf3_page_generation_error_bytesTb4b4b4(Ta5d6ff"Ta5d6ffThe page script timed out.Ta5d6ff"Tb4b4b4)
Tff7b72except Tf85149OSError Tff7b72as Te6edf3eTb4b4b4:
Tff7b72return Te6edf3_page_generation_error_bytesTb4b4b4(Tffa657strTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Tff7b72return Te6edf3_page_generation_error_bytesTb4b4b4(Tffa657strTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4)
Tff7b72def Td2a8ffserve_page_contentTb4b4b4(
Tff7b72selfTb4b4b4,
Te6edf3nameTb4b4b4,
Te6edf3dataTff7b72=Tff7b72NoneTb4b4b4,
Te6edf3link_idTff7b72=Tff7b72NoneTb4b4b4,
Te6edf3remote_identityTff7b72=Tff7b72NoneTb4b4b4,
Tb4b4b4)Tb4b4b4:
T8b949e"""Serve a page as static bytes or by executing it when enabled and executable."""
Te6edf3page_path Tff7b72= Tff7b72selfTff7b72.Td2a8ff_resolve_page_pathTb4b4b4(Te6edf3nameTb4b4b4)
Tff7b72if Te6edf3page_path Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Tff7b72None
Tff7b72tryTb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ff_should_execute_pageTb4b4b4(Te6edf3page_pathTb4b4b4)Tb4b4b4:
Te6edf3content Tff7b72= Tff7b72selfTff7b72.Td2a8ff_execute_page_bytesTb4b4b4(
Te6edf3page_pathTb4b4b4,
Te6edf3dataTff7b72=Te6edf3dataTb4b4b4,
Te6edf3link_idTff7b72=Te6edf3link_idTb4b4b4,
Te6edf3remote_identityTff7b72=Te6edf3remote_identityTb4b4b4,
Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3content Tff7b72= Tff7b72selfTff7b72.Td2a8ff_read_static_page_bytesTb4b4b4(Te6edf3page_pathTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_statsTb4b4b4[Ta5d6ff"Ta5d6ffpages_servedTa5d6ff"Tb4b4b4] Tff7b72+Tff7b72= T79c0ff1
Tff7b72return Te6edf3content
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72return Tff7b72None
Tff7b72def Td2a8ff_make_page_responderTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3page_nameTb4b4b4)Tb4b4b4:
T8b949e"""Return a closure that serves a specific page."""
Tff7b72def Td2a8ffresponderTb4b4b4(Te6edf3pathTb4b4b4, Te6edf3dataTb4b4b4, Te6edf3request_idTb4b4b4, Te6edf3link_idTb4b4b4, Te6edf3remote_identityTb4b4b4, Te6edf3requested_atTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_note_remote_identityTb4b4b4(Te6edf3remote_identityTb4b4b4)
Tff7b72return Tff7b72selfTff7b72.Td2a8ffserve_page_contentTb4b4b4(
Te6edf3page_nameTb4b4b4,
Te6edf3dataTff7b72=Te6edf3dataTb4b4b4,
Te6edf3link_idTff7b72=Te6edf3link_idTb4b4b4,
Te6edf3remote_identityTff7b72=Te6edf3remote_identityTb4b4b4,
Tb4b4b4)
Tff7b72return Te6edf3responder
Tff7b72def Td2a8ff_jail_file_pathTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3nameTb4b4b4, Tff7b72*Tb4b4b4, Te6edf3must_existTff7b72=Tff7b72FalseTb4b4b4)Tb4b4b4:
T8b949e"""Resolve a hosted file name under files_dir after realpath.
Returns None when the name is invalid, the path escapes the jail
(including symlink-out), or must_exist is set and the file is missing.
"""
Tff7b72tryTb4b4b4:
Te6edf3safe_name Tff7b72= Te6edf3_safe_mesh_file_basenameTb4b4b4(Te6edf3nameTb4b4b4)
Te6edf3_reject_name_component_too_longTb4b4b4(Tff7b72selfTff7b72.Td2a8fffiles_dirTb4b4b4, Te6edf3safe_nameTb4b4b4)
Tff7b72except Tf85149ValueErrorTb4b4b4:
Tff7b72return Tff7b72None
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Tff7b72selfTff7b72.Td2a8fffiles_dirTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72None
Te6edf3root Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffrealpathTb4b4b4(Tff7b72selfTff7b72.Td2a8fffiles_dirTb4b4b4)
Te6edf3raw Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3rootTb4b4b4, Te6edf3safe_nameTb4b4b4)
Te6edf3resolved Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffrealpathTb4b4b4(Te6edf3rawTb4b4b4)
Tff7b72if Tff7b72not Te6edf3_path_is_under_rootTb4b4b4(Te6edf3resolvedTb4b4b4, Te6edf3rootTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72None
Tff7b72if Te6edf3must_exist Tff7b72and Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisfileTb4b4b4(Te6edf3resolvedTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72None
Tff7b72return Te6edf3resolved
Tff7b72def Td2a8ffread_hosted_fileTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3nameTb4b4b4)Tb4b4b4:
T8b949e"""Read a hosted file from the files jail.
Returns (file_name, file_bytes), or None.
"""
Te6edf3file_path Tff7b72= Tff7b72selfTff7b72.Td2a8ff_jail_file_pathTb4b4b4(Te6edf3nameTb4b4b4, Te6edf3must_existTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72if Te6edf3file_path Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Tff7b72None
Tff7b72tryTb4b4b4:
Tff7b72with Tffa657openTb4b4b4(Te6edf3file_pathTb4b4b4, Ta5d6ff"Ta5d6ffrbTa5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3file_bytes Tff7b72= Te6edf3fTff7b72.Td2a8ffreadTb4b4b4(Tb4b4b4)
Tff7b72except Tf85149OSErrorTb4b4b4:
Tff7b72return Tff7b72None
Tff7b72selfTff7b72.Td2a8ff_statsTb4b4b4[Ta5d6ff"Ta5d6fffiles_servedTa5d6ff"Tb4b4b4] Tff7b72+Tff7b72= T79c0ff1
Tff7b72return Tb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffbasenameTb4b4b4(Te6edf3file_pathTb4b4b4)Tb4b4b4, Te6edf3file_bytesTb4b4b4)
Tff7b72def Td2a8ff_make_file_responderTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3file_nameTb4b4b4)Tb4b4b4:
T8b949e"""Return a closure that serves a specific file."""
Tff7b72def Td2a8ffresponderTb4b4b4(Te6edf3pathTb4b4b4, Te6edf3dataTb4b4b4, Te6edf3request_idTb4b4b4, Te6edf3link_idTb4b4b4, Te6edf3remote_identityTb4b4b4, Te6edf3requested_atTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_note_remote_identityTb4b4b4(Te6edf3remote_identityTb4b4b4)
Te6edf3file_path Tff7b72= Tff7b72selfTff7b72.Td2a8ff_jail_file_pathTb4b4b4(Te6edf3file_nameTb4b4b4, Te6edf3must_existTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72if Te6edf3file_path Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Tff7b72None
Tff7b72tryTb4b4b4:
Te6edf3fh Tff7b72= Tffa657openTb4b4b4(Te6edf3file_pathTb4b4b4, Ta5d6ff"Ta5d6ffrbTa5d6ff"Tb4b4b4)
Te6edf3metadata Tff7b72= Tb4b4b4{Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4: Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffbasenameTb4b4b4(Te6edf3file_pathTb4b4b4)Tff7b72.Td2a8ffencodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4)Tb4b4b4}
Tff7b72selfTff7b72.Td2a8ff_statsTb4b4b4[Ta5d6ff"Ta5d6fffiles_servedTa5d6ff"Tb4b4b4] Tff7b72+Tff7b72= T79c0ff1
Tff7b72return Tb4b4b4[Te6edf3fhTb4b4b4, Te6edf3metadataTb4b4b4]
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72return Tff7b72None
Tff7b72return Te6edf3responder
Tff7b72def Td2a8ffadd_pageTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3nameTb4b4b4, Te6edf3contentTb4b4b4, Te6edf3executableTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
T8b949e"""Write a page file and register its request handler."""
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Tff7b72selfTff7b72.Td2a8ffpages_dirTb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)
Te6edf3page_path Tff7b72= Tff7b72selfTff7b72.Td2a8ff_jail_page_pathTb4b4b4(Te6edf3nameTb4b4b4, Te6edf3must_existTff7b72=Tff7b72FalseTb4b4b4)
Tff7b72if Te6edf3page_path Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6ff"Ta5d6ffinvalid page nameTa5d6ff"Tb4b4b4)
Te6edf3name Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffbasenameTb4b4b4(Te6edf3page_pathTb4b4b4)
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3contentTb4b4b4, Tffa657strTb4b4b4)Tb4b4b4:
Te6edf3content Tff7b72= Te6edf3contentTff7b72.Td2a8ffencodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4)
Tff7b72with Tffa657openTb4b4b4(Te6edf3page_pathTb4b4b4, Ta5d6ff"Ta5d6ffwbTa5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3fTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3contentTb4b4b4)
Tff7b72if Te6edf3executable Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffset_page_executableTb4b4b4(Te6edf3nameTb4b4b4, Tffa657boolTb4b4b4(Te6edf3executableTb4b4b4)Tb4b4b4)
Tff7b72if Tff7b72selfTff7b72.Td2a8ffrunningTb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_register_page_handlerTb4b4b4(Te6edf3nameTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Tff7b72raise Tf85149RuntimeErrorTb4b4b4(
Ta5d6fffTa5d6ff"Ta5d6ffPage written but failed to register on mesh: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4,
Tb4b4b4) Tff7b72from T7ee787e
Tff7b72return Te6edf3name
Tff7b72def Td2a8ffremove_pageTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3nameTb4b4b4)Tb4b4b4:
T8b949e"""Remove a page and deregister its request handler."""
Te6edf3page_path Tff7b72= Tff7b72selfTff7b72.Td2a8ff_jail_page_pathTb4b4b4(Te6edf3nameTb4b4b4, Te6edf3must_existTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72if Te6edf3page_path Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Tff7b72False
Tff7b72tryTb4b4b4:
Te6edf3name Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffbasenameTb4b4b4(Te6edf3page_pathTb4b4b4)
Te6edf3osTff7b72.Td2a8ffremoveTb4b4b4(Te6edf3page_pathTb4b4b4)
Tff7b72except Tf85149OSErrorTb4b4b4:
Tff7b72return Tff7b72False
Tff7b72selfTff7b72.Td2a8ff_executable_page_namesTff7b72.Td2a8ffdiscardTb4b4b4(Te6edf3nameTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffsave_configTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_deregister_page_handlerTb4b4b4(Te6edf3nameTb4b4b4)
Tff7b72return Tff7b72True
Tff7b72def Td2a8fflist_pagesTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Return page metadata dicts with name and executable state."""
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Tff7b72selfTff7b72.Td2a8ffpages_dirTb4b4b4)Tb4b4b4:
Tff7b72return Tb4b4b4[Tb4b4b4]
Te6edf3pages Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72for Te6edf3fname Tff7b72in Tffa657sortedTb4b4b4(Te6edf3osTff7b72.Td2a8fflistdirTb4b4b4(Tff7b72selfTff7b72.Td2a8ffpages_dirTb4b4b4)Tb4b4b4)Tb4b4b4:
Te6edf3fpath Tff7b72= Tff7b72selfTff7b72.Td2a8ff_jail_page_pathTb4b4b4(Te6edf3fnameTb4b4b4, Te6edf3must_existTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72if Te6edf3fpath Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72continue
Te6edf3pagesTff7b72.Td2a8ffappendTb4b4b4(
Tb4b4b4{
Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4: Te6edf3fnameTb4b4b4,
Ta5d6ff"Ta5d6ffexecutableTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffis_page_executableTb4b4b4(Te6edf3fnameTb4b4b4)Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tff7b72return Te6edf3pages
Tff7b72def Td2a8ffget_page_contentTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3nameTb4b4b4)Tb4b4b4:
T8b949e"""Read and return a page's content."""
Te6edf3page_path Tff7b72= Tff7b72selfTff7b72.Td2a8ff_jail_page_pathTb4b4b4(Te6edf3nameTb4b4b4, Te6edf3must_existTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72if Te6edf3page_path Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Tff7b72None
Tff7b72with Tffa657openTb4b4b4(Te6edf3page_pathTb4b4b4, Te6edf3encodingTff7b72=Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Tff7b72return Te6edf3fTff7b72.Td2a8ffreadTb4b4b4(Tb4b4b4)
Tff7b72def Td2a8ffadd_fileTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3nameTb4b4b4, Te6edf3dataTb4b4b4)Tb4b4b4:
T8b949e"""Write a file and register its request handler."""
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Tff7b72selfTff7b72.Td2a8fffiles_dirTb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)
Te6edf3name Tff7b72= Te6edf3_safe_mesh_file_basenameTb4b4b4(Te6edf3nameTb4b4b4)
Te6edf3_reject_name_component_too_longTb4b4b4(Tff7b72selfTff7b72.Td2a8fffiles_dirTb4b4b4, Te6edf3nameTb4b4b4)
Te6edf3file_path Tff7b72= Tff7b72selfTff7b72.Td2a8ff_jail_file_pathTb4b4b4(Te6edf3nameTb4b4b4, Te6edf3must_existTff7b72=Tff7b72FalseTb4b4b4)
Tff7b72if Te6edf3file_path Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6ff"Ta5d6ffinvalid file nameTa5d6ff"Tb4b4b4)
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3dataTb4b4b4, Tffa657strTb4b4b4)Tb4b4b4:
Te6edf3data Tff7b72= Te6edf3dataTff7b72.Td2a8ffencodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4)
Tff7b72with Tffa657openTb4b4b4(Te6edf3file_pathTb4b4b4, Ta5d6ff"Ta5d6ffwbTa5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3fTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3dataTb4b4b4)
Tff7b72if Tff7b72selfTff7b72.Td2a8ffrunningTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_register_file_handlerTb4b4b4(Te6edf3nameTb4b4b4)
Tff7b72return Te6edf3name
Tff7b72def Td2a8ffremove_fileTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3nameTb4b4b4)Tb4b4b4:
T8b949e"""Remove a file and deregister its request handler."""
Te6edf3file_path Tff7b72= Tff7b72selfTff7b72.Td2a8ff_jail_file_pathTb4b4b4(Te6edf3nameTb4b4b4, Te6edf3must_existTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72if Te6edf3file_path Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Tff7b72False
Tff7b72tryTb4b4b4:
Te6edf3name Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffbasenameTb4b4b4(Te6edf3file_pathTb4b4b4)
Te6edf3osTff7b72.Td2a8ffremoveTb4b4b4(Te6edf3file_pathTb4b4b4)
Tff7b72except Tf85149OSErrorTb4b4b4:
Tff7b72return Tff7b72False
Tff7b72selfTff7b72.Td2a8ff_deregister_file_handlerTb4b4b4(Te6edf3nameTb4b4b4)
Tff7b72return Tff7b72True
Tff7b72def Td2a8fflist_filesTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Return a list of file dicts with name and size."""
Tff7b72if Tff7b72selfTff7b72.Td2a8ffrunningTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_register_existing_filesTb4b4b4(Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Tff7b72selfTff7b72.Td2a8fffiles_dirTb4b4b4)Tb4b4b4:
Tff7b72return Tb4b4b4[Tb4b4b4]
Te6edf3result Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72for Te6edf3fname Tff7b72in Tffa657sortedTb4b4b4(Te6edf3osTff7b72.Td2a8fflistdirTb4b4b4(Tff7b72selfTff7b72.Td2a8fffiles_dirTb4b4b4)Tb4b4b4)Tb4b4b4:
Te6edf3fpath Tff7b72= Tff7b72selfTff7b72.Td2a8ff_jail_file_pathTb4b4b4(Te6edf3fnameTb4b4b4, Te6edf3must_existTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72if Te6edf3fpath Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72continue
Te6edf3resultTff7b72.Td2a8ffappendTb4b4b4(Tb4b4b4{Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4: Te6edf3fnameTb4b4b4, Ta5d6ff"Ta5d6ffsizeTa5d6ff"Tb4b4b4: Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffgetsizeTb4b4b4(Te6edf3fpathTb4b4b4)Tb4b4b4}Tb4b4b4)
Tff7b72return Te6edf3result
Tff7b72def Td2a8ffget_destination_hashTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Return the hex destination hash if running."""
Tff7b72if Tff7b72selfTff7b72.Td2a8ffdestinationTb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8ffhashTff7b72.Td2a8ffhexTb4b4b4(Tb4b4b4)
Tff7b72return Tff7b72None
Tff7b72def Td2a8ffget_statusTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Return current node status dict."""
Te6edf3uptime_seconds Tff7b72= T79c0ff0
Tff7b72if Tff7b72selfTff7b72.Td2a8ffrunning Tff7b72and Tff7b72selfTff7b72.Td2a8ff_serve_started_at Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Te6edf3uptime_seconds Tff7b72= Tffa657maxTb4b4b4(T79c0ff0Tb4b4b4, Tffa657intTb4b4b4(Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4) Tff7b72- Tff7b72selfTff7b72.Td2a8ff_serve_started_atTb4b4b4)Tb4b4b4)
Tff7b72return Tb4b4b4{
Ta5d6ff"Ta5d6ffnode_idTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffnode_idTb4b4b4,
Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffnameTb4b4b4,
Ta5d6ff"Ta5d6ffrunningTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffrunningTb4b4b4,
Ta5d6ff"Ta5d6ffdestination_hashTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffget_destination_hashTb4b4b4(Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffidentity_hashTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffidentityTff7b72.Td2a8ffhashTff7b72.Td2a8ffhexTb4b4b4(Tb4b4b4) Tff7b72if Tff7b72selfTff7b72.Td2a8ffidentity Tff7b72else Tff7b72NoneTb4b4b4,
Ta5d6ff"Ta5d6ffactive_linksTa5d6ff"Tb4b4b4: Tffa657lenTb4b4b4(Tff7b72selfTff7b72.Td2a8ffactive_linksTb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffunique_connectionsTa5d6ff"Tb4b4b4: Tffa657lenTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_unique_remote_hashesTb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffuptime_secondsTa5d6ff"Tb4b4b4: Te6edf3uptime_secondsTb4b4b4,
Ta5d6ff"Ta5d6ffpagesTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8fflist_pagesTb4b4b4(Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6fffilesTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8fflist_filesTb4b4b4(Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffstatsTa5d6ff"Tb4b4b4: Tffa657dictTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_statsTb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffannounce_enabledTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffannounce_enabledTb4b4b4,
Ta5d6ff"Ta5d6ffannounce_interval_secondsTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffannounce_interval_secondsTb4b4b4,
Ta5d6ff"Ta5d6ffexecutable_pages_enabledTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffexecutable_pages_enabledTb4b4b4,
Ta5d6ff"Ta5d6fflast_announced_atTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8fflast_announced_atTb4b4b4,
Tb4b4b4}
Tff7b72def Td2a8ffsave_configTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Persist node configuration to disk."""
Te6edf3config Tff7b72= Tb4b4b4{
Ta5d6ff"Ta5d6ffnode_idTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffnode_idTb4b4b4,
Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffnameTb4b4b4,
Ta5d6ff"Ta5d6ffannounce_enabledTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffannounce_enabledTb4b4b4,
Ta5d6ff"Ta5d6ffannounce_interval_secondsTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffannounce_interval_secondsTb4b4b4,
Ta5d6ff"Ta5d6ffexecutable_pages_enabledTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffexecutable_pages_enabledTb4b4b4,
Ta5d6ff"Ta5d6ffexecutable_page_namesTa5d6ff"Tb4b4b4: Tffa657sortedTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_executable_page_namesTb4b4b4)Tb4b4b4,
Tb4b4b4}
Te6edf3config_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffbase_dirTb4b4b4, Ta5d6ff"Ta5d6ffconfig.jsonTa5d6ff"Tb4b4b4)
Tff7b72with Tffa657openTb4b4b4(Te6edf3config_pathTb4b4b4, Ta5d6ff"Ta5d6ffwTa5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3jsonTff7b72.Td2a8ffdumpTb4b4b4(Te6edf3configTb4b4b4, Te6edf3fTb4b4b4, Te6edf3indentTff7b72=T79c0ff2Tb4b4b4)
Tf0883e@staticmethod
Tff7b72def Td2a8ffload_configTb4b4b4(Te6edf3base_dirTb4b4b4)Tb4b4b4:
T8b949e"""Load node configuration from disk. Returns dict or None."""
Te6edf3config_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3base_dirTb4b4b4, Ta5d6ff"Ta5d6ffconfig.jsonTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisfileTb4b4b4(Te6edf3config_pathTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72None
Tff7b72with Tffa657openTb4b4b4(Te6edf3config_pathTb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Tff7b72return Te6edf3jsonTff7b72.Td2a8ffloadTb4b4b4(Te6edf3fTb4b4b4)
Served by rngit 1.4.2 - Generated in 0.07s